package com.mc.test;

import java.util.Stack;
import java.util.regex.Pattern;

/**
 * @Description: 后缀表达式
 * @Author: MoChen
 */
public class PolishNotation {

    // 中缀表达式
    private static String notation = "((15 / (7 - (1 + 1))) * 3) - (2 + (1 + 1))";
    // 后缀表达式
    private static String poNotation = "15 7 1 1 + - / 3 * 2 1 1 + + -";
    // 前缀表达式
    private static String rpoNotation = "- * / 15 - 7 + 1 1 3 + 2 + 1 1";
    // 10的倍数
    private static int[] exactNums = {10, 100, 1000, 10000, 100000};

    public static void main(String[] args) {
        System.out.println("中计算：" + countNum(notation));
//        System.out.println("中转后：" + commTransRpo(notation));
//        System.out.println("后计算：" + poCount(poNotation));
    }

    /**
     * 中缀转后缀
     */
    static String commTransRpo(String notation){
        StringBuilder str = new StringBuilder();
        Stack<Character> stack = new Stack<>();
        char[] chars = notation.toCharArray();

        for(int i = 0; i < chars.length; i++){
            if(isInteger(chars[i] + "")){
                int j = 1;
                int num = Integer.parseInt(chars[i] + "");
                while(isInteger(chars[i + j] + "")){
                    num = Integer.parseInt(num + "" + chars[i + j] + "");
                    j++;
                }
                i += j - 1;
                str.append(num).append(" ");
            }else if(chars[i] != ' '){
                if(chars[i] == '('){
                    stack.push(chars[i]);
                }else if(chars[i] == ')' && !stack.empty()){
                    char pop = stack.pop();
                    while(pop != '('){
                        str.append(pop + " ");
                        pop = stack.pop();
                    }
                }else{
                    switch (chars[i]){
                        case '+':
                        case '-':
                            if(!stack.empty() && stack.peek() != '('){
                                while(!stack.empty()){
                                    char pop = stack.pop();
                                    if(pop != '(' && pop != ')'){
                                        str.append(pop + " ");
                                    }
                                }
                            }else{
                                stack.push(chars[i]);
                            }
                            break;
                        case '*':
                        case '/':
                            if(!stack.empty() && stack.peek() != '(' && stack.peek() != '-' && stack.peek() != '+'){
                                while(!stack.empty()){
                                    char pop = stack.pop();
                                    if(pop != '(' && pop != ')'){
                                        str.append(pop + " ");
                                    }
                                }
                            }else{
                                stack.push(chars[i]);
                            }
                            break;
                    }
                }
            }
        }
        while(!stack.empty()){
            str.append(stack.pop());
        }
        return str.toString();
    }

    /**
     * 后缀计算
     */
    static Integer poCount(String notation){
        int res = 0;
        Stack<Integer> stack = new Stack<>();
        char[] chars = notation.toCharArray();
        boolean count = false;

        for(int i = 0; i < chars.length; i++){
            if(isInteger(chars[i] + "")){
                int j = 1;
                int num = Integer.parseInt(chars[i] + "");
                while(isInteger(chars[i + j] + "")){
                    num = Integer.parseInt(num + "" + chars[i + j] + "");
                    j++;
                }
                i += j - 1;
                stack.push(num);
            }else if(chars[i] != ' '){
                int temp = stack.pop();
                switch (chars[i]){
                    case '+':
                        stack.push(stack.pop() + temp);
                        break;
                    case '-':
                        stack.push(stack.pop() - temp);
                        break;
                    case '*':
                        stack.push(stack.pop() * temp);
                        break;
                    case '/':
                        stack.push(stack.pop() / temp);
                        break;
                }
            }
        }
        res = stack.pop();
        return res;
    }

    /**
     * 求和（中缀）
     */
    static Integer countNum(String notation){
        return poCount(commTransRpo(notation));
    }

    /**
     * 前缀计算
     */
    static Integer rpoCount(String notation){
        Stack<Integer> stack = new Stack<>();
        char[] chars = notation.toCharArray();
        for(int i = chars.length - 1; i >= 0; i--){
            if(chars[i] != ' '){
                switch (chars[i]){
                    case '+':
                        stack.push(stack.pop() + stack.pop());
                        break;
                    case '-':
                        stack.push(stack.pop() - stack.pop());
                        break;
                    case '*':
                        stack.push(stack.pop() * stack.pop());
                        break;
                    case '/':
                        stack.push(stack.pop() / stack.pop());
                        break;
                    default:
                        int num = Integer.parseInt(chars[i] + "");
                        int j = 1;
                        while(isInteger(chars[i - j] + "")){
                            num = num + Integer.parseInt(chars[i - j] + "") * exactNums[j - 1];
                            j++;
                            i--;
                            System.out.println("?");
                        }
                        stack.push(num);
                        System.out.println(stack.toString());
                        break;
                }
            }
        }
        return stack.pop();
    }

    /**
     * 判断一个字符是否为Integer
     */
    public static boolean isInteger(String str) {
        Pattern pattern = Pattern.compile("[0-9]*");
        return pattern.matcher(str).matches();
    }
}
